Skip to content

feat: Introduce Downloads Archive page #7794

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 62 commits into
base: main
Choose a base branch
from

Conversation

canerakdas
Copy link
Member

@canerakdas canerakdas commented May 31, 2025

Description

This PR introduces a new statically generated page that displays simplified download options by major version:

image

Also includes a download table of other minor versions of the major version;
image

Since I included the minor versions as a table, the content became quite lengthy. To prevent this, I used the HTML details element. The main reason I didn't use Radix Primitive Accordion is that we want this page to be fully usable even for users who have JavaScript disabled

I am open to suggestions for to add / remove content 🙇

Validation

The links below are accessible in the preview;

  • /download/{major}
  • /download/archive

Related Issues

Addresses #7443

Check List

  • I have read the Contributing Guidelines and made commit messages that follow the guideline.
  • I have run pnpm format to ensure the code follows the style guide.
  • I have run pnpm test to check if all tests are passing.
  • I have run pnpm build to check if the website builds without errors.
  • I've covered new added functionality with unit tests if necessary.

@Copilot Copilot AI review requested due to automatic review settings May 31, 2025 12:02
@canerakdas canerakdas requested a review from a team as a code owner May 31, 2025 12:02
Copy link

vercel bot commented May 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nodejs-org Ready Ready Preview Aug 16, 2025 9:24pm

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new simplified downloads page that’s fully server-rendered (no JS required) and provides major‐version download summaries, with expandable minor versions under <details>. It also centralizes download utilities and updates the download URL API to use an options object.

  • Introduce simplified.mdx and DownloadSimpleLayout for the new page
  • Update getNodeDownloadUrl signature and its callers to use an options object
  • Add DownloadsTable, Details, and WithSimplifiedDownload components

Reviewed Changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
util/downloadUtils/index.tsx Exported DownloadDropdownItem type
util/downloadUtils/constants.json Added compatibility ranges for platforms
util/tests/getNodeDownloadUrl.test.mjs Updated tests for new getNodeDownloadUrl signature
types/layouts.ts Added 'download-simple' layout type
pages/en/download/simplified.mdx New MDX page with simplified download UI
next.mdx.use.mjs Registered new MDX components (WithSimplifiedDownload, etc.)
next.dynamic.constants.mjs Configured dynamic routing and exclusions for new page
layouts/DownloadSimple.tsx New layout wrapping simplified download content
components/withSimplifiedDownload.tsx HOC to provide download data and sidebar items
components/withProgressionSidebar.tsx Refactored to accept both navKey and explicit groups
components/withMetaBar.tsx Made items injectable for meta‐bar
components/withMarkdownContent.tsx New HOC to load MDX content at runtime
components/withLayout.tsx Added DownloadSimpleLayout to layout mapping
components/MDX/Details New <Details> component for collapsible sections
components/Downloads/Release/ReleaseCodeBox.tsx Updated “no-script” link to point at new simplified page
components/Downloads/Release/PrebuiltDownloadButtons.tsx Switched getNodeDownloadUrl calls to object syntax
components/Downloads/DownloadsTable New table for listing artifacts
components/Downloads/DownloadLink.tsx Updated to new getNodeDownloadUrl API
components/Downloads/DownloadButton Updated to new getNodeDownloadUrl API
Comments suppressed due to low confidence (1)

apps/site/components/Downloads/DownloadsTable/index.tsx:1

  • Consider adding unit tests for DownloadsTable to verify it renders rows correctly for different source inputs.
'use client';

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Caner Akdas <canerakdas@gmail.com>
Copy link
Contributor

github-actions bot commented Aug 10, 2025

Lighthouse Results

URL Performance Accessibility Best Practices SEO Report
/en 🟢 90 🟢 100 🟢 100 🟢 100 🔗
/en/about 🟢 99 🟢 97 🟢 100 🟠 88 🔗
/en/about/previous-releases 🟢 99 🟢 93 🟢 100 🟠 89 🔗
/en/download 🟢 95 🟢 100 🟢 100 🟢 100 🔗
/en/blog 🟢 99 🟢 100 🟢 96 🟢 100 🔗

@ovflowd
Copy link
Member

ovflowd commented Aug 15, 2025

cc @canerakdas could you rebase for a final review?

// that should be rendered.
if (
staticGeneratedLayout !== undefined &&
!DYNAMIC_MARKDOWN_ROUTES.has(staticGeneratedLayout)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can remove this check and simply attempt to retrieve markdown, and if there's nothing, then there's nothing :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove this check, the dynamic markdown pages will also be processed as if they were static. As a result, for dynamic markdown pages, anything other than the default path (download/archive) would render as an empty page

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* @returns {Promise<Array<string>>}
*/
const generateAllVersionsData = async () => {
const nodevuOutput = await nodevu({ fetch });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we're fetching this request twice, I wonder if the browser will dedupe the request?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two separate requests are being made. In fact, we’re already retrieving this information for the release data generator, so instead of making another request, it would be better to use the release data provider while generating the versions for now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already use top-level awaits for the providers, so maybe the reqauest to await nodevu() could be done in a separate file, also as a top-level await?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at the very least as a Promise? Like:

export default nodevu({ fetch });

Import it and await it on generateAllVersionsData and the other generator?

return Object.entries(platforms).flatMap(([os, items]) => {
if (exclude.includes(os)) return [];

const operatingSystem = os as OperatingSystem;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid the casting here? I assume os will be marked as "string"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os is marked as ; "AIX" | "MAC" | "LINUX" | "OTHER" | "WIN" | "LOADING" 🥹

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just don't think you need to assign a new constant, you can do the casting directly on usage no? Or just allow the sibling function to receive a string IDK, since there's a switch statement anyways.

@canerakdas
Copy link
Member Author

I’ll do another round of self-review tomorrow to check if there’s any spot I missed while resolving the conflicts. For now, there might be something I’ve overlooked 👀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplified Downloads page for non-JS-enabled environments
6 participants